package xmu.crms.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import xmu.crms.entity.*;
import xmu.crms.exception.*;
import xmu.crms.service.*;
import xmu.crms.vo.*;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author badcode
 * @date 2017/11/29
 */
@RestController
@RequestMapping("/seminar")
public class SeminarController {

    @Autowired
    private SeminarService seminarService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private SeminarGroupService seminarGroupService;

    @Autowired
    private TopicService topicService;

    @Autowired
    private UserService userService;

    @Autowired
    private ClassService classService;

    @GetMapping("/{seminarId}")
    @ResponseStatus(HttpStatus.OK)
    public SeminarVO getSeminarInfo(@PathVariable("seminarId") String seminarId) throws SeminarNotFoundException {
        SeminarVO seminarVO = new SeminarVO();
        Seminar seminar = seminarService.getSeminarBySeminarId(new BigInteger(seminarId));
        System.out.println(seminar);
        seminarVO.setId(seminar.getId().longValue());
        seminarVO.setName(seminar.getName());
        seminarVO.setDescription(seminar.getDescription());
        seminarVO.setGroupingMethod(seminar.getFixed() ? "fixed" : "random");
        seminarVO.setStartTime(seminar.getStartTime());
        seminarVO.setEndTime(seminar.getEndTime());
        List<TopicBasicVO> topicBasicVOS = new ArrayList<>();
        List<Topic> topics = topicService.listTopicBySeminarId(new BigInteger(seminarId));
        for (Topic topic : topics
                ) {
            TopicBasicVO topicBasicVO = new TopicBasicVO();
            topicBasicVO.setId(topic.getId().longValue());
            topicBasicVO.setName(topic.getName());
            topicBasicVOS.add(topicBasicVO);
        }
        seminarVO.setTopics(topicBasicVOS);
        return seminarVO;
    }

    @PutMapping("/{seminarId}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void modifySeminar(@PathVariable("seminarId") String seminarId, @RequestBody SeminarProportionsVO seminarVO)
            throws SeminarNotFoundException {
        Seminar seminar = new Seminar();
        seminar.setId(new BigInteger(seminarId));
        seminar.setName(seminarVO.getName());
        seminar.setDescription(seminarVO.getDescription());
        seminar.setFixed(seminarVO.getGroupingMethod() == "fixed" ? true : false);
        seminar.setStartTime(seminarVO.getStartTime());
        seminar.setEndTime(seminarVO.getEndTime());
        seminarService.updateSeminarBySeminarId(new BigInteger(seminarId), seminar);
    }

    @DeleteMapping("/{seminarId}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteSeminar(@PathVariable("seminarId") String seminarId) throws SeminarNotFoundException {
        seminarService.deleteSeminarBySeminarId(new BigInteger(seminarId));
    }

    @GetMapping("/{seminarId}/my")
    @ResponseStatus(HttpStatus.OK)
    public StudentSeminar getRelatedSeminar(@PathVariable("seminarId") String seminarId,@RequestAttribute("userId") String userId)
            throws SeminarNotFoundException, CourseNotFoundException, ClassesNotFoundException, GroupNotFoundException {

        StudentSeminar studentSeminar = new StudentSeminar();
        Seminar seminar = seminarService.getSeminarBySeminarId(new BigInteger(seminarId));
        studentSeminar.setId(seminar.getId().longValue());
        studentSeminar.setName(seminar.getName());
        if (seminar.getFixed() == true) {
            studentSeminar.setGroupingMethond("fixed");
        } else {
            studentSeminar.setGroupingMethond("random");
        }

        Course course = courseService.getCourseByCourseId(seminar.getCourse().getId());
        studentSeminar.setCourseName(course.getName());

        studentSeminar.setStartTime(seminar.getStartTime());
        studentSeminar.setEndTime(seminar.getEndTime());

        BigInteger classId = new BigInteger("-1");
        List<ClassInfo> classInfos = classService.listClassByUserId(new BigInteger(userId));
        for (ClassInfo classInfo : classInfos
                ) {
            if (classInfo.getCourse().getId().equals(course.getId())) {
                classId = classInfo.getId();
                studentSeminar.setClassCalling(classId.intValue());
                break;
            }
        }

        BigInteger leaderId = seminarGroupService.getSeminarGroupLeaderById(new BigInteger(userId), new BigInteger(seminarId));
        if (userId.equals(leaderId)) {
            studentSeminar.setIsLeader("true");
        } else {
            studentSeminar.setIsLeader("false");
        }
        List<Topic> topics = topicService.listTopicBySeminarId(new BigInteger(seminarId));
        SeminarGroup seminarGroup = seminarGroupService.getSeminarGroupById(new BigInteger(seminarId), new BigInteger(userId));
        BigInteger groupId = seminarGroup.getId();
        Boolean areTopicsSelected = false;
        for (Topic topic : topics
                ) {
            SeminarGroupTopic seminarGroupTopic = topicService.getSeminarGroupTopicById(topic.getId(), groupId);
            if (seminarGroupTopic != null) {
                areTopicsSelected = true;
                break;
            }
        }
        if (areTopicsSelected) {
            studentSeminar.setAreTopicsSelected("true");
        } else {
            studentSeminar.setAreTopicsSelected("true");
        }
        studentSeminar.setAreTopicsSelected("false");

        return studentSeminar;
    }

    @GetMapping("/{seminarId}/detail")
    @ResponseStatus(HttpStatus.OK)
    public SeminarDetail getSeminarDetail(@PathVariable("seminarId") String seminarId,@RequestAttribute("userId") String userId)
            throws SeminarNotFoundException, CourseNotFoundException, ClassesNotFoundException, UserNotFoundException {
        SeminarDetail seminarDetail = new SeminarDetail();

        Seminar seminar = seminarService.getSeminarBySeminarId(new BigInteger(seminarId));
        seminarDetail.setId(seminar.getId().longValue());
        seminarDetail.setName(seminar.getName());
        seminarDetail.setStartTime(seminar.getStartTime());
        seminarDetail.setEndTime(seminar.getEndTime());

        Course course = courseService.getCourseByCourseId(seminar.getCourse().getId());
        List<ClassInfo> classInfos = classService.listClassByUserId(new BigInteger(userId));
        ClassInfo classInfo = new ClassInfo();
        for (ClassInfo classInfo1 : classInfos
                ) {
            if (classInfo1.getCourse().getId().equals(course.getId())) {
                classInfo = classInfo1;
                break;
            }
        }
        if (classInfo == null) {
            throw new ClassesNotFoundException();
        } else {
            seminarDetail.setSite(classInfo.getSite());
        }

        User teacher = userService.getUserByUserId(course.getTeacher().getId());
        seminarDetail.setTeacherName(teacher.getName());
        seminarDetail.setTeacherEmail(teacher.getEmail());

        return seminarDetail;
    }

    @GetMapping("/{seminarId}/topic")
    @ResponseStatus(HttpStatus.OK)
    public List<TopicVO> getTopics(@PathVariable("seminarId") String seminarId) throws IllegalArgumentException {
        List<TopicVO> topicVOS = new ArrayList<>();
        List<Topic> topics = topicService.listTopicBySeminarId(new BigInteger(seminarId));
        for (Topic topic : topics
                ) {
            TopicVO topicVO = new TopicVO();
            topicVO.setId(topic.getId());
            topicVO.setSerial(topic.getSerial());
            topicVO.setName(topic.getName());
            topicVO.setDescription(topic.getDescription());
            topicVO.setGroupLimit(topic.getGroupNumberLimit());
            topicVO.setGroupMemberLimit(topic.getGroupStudentLimit());

            topicVOS.add(topicVO);
        }
        return topicVOS;
    }

    @PostMapping("/{seminarId}/topic")
    @ResponseStatus(HttpStatus.CREATED)
    public Topic addTopic(@PathVariable("seminarId") String seminarId, @RequestBody TopicVO topicVO) {
        Topic topic = new Topic();
        topic.setSerial(topicVO.getSerial());
        topic.setName(topicVO.getName());
        topic.setDescription(topicVO.getDescription());
        topic.setGroupNumberLimit(topicVO.getGroupLimit());
        topic.setGroupStudentLimit(topicVO.getGroupLimit());
        BigInteger id = topicService.insertTopicBySeminarId(new BigInteger(seminarId), topic);
        Topic newTopic = new Topic();
        newTopic.setId(id);
        return newTopic;
    }

    @GetMapping("/{seminarId}/group")
    @ResponseStatus(HttpStatus.OK)
    public List<TeacherScoreVO> getGroups(@PathVariable("seminarId") String seminarId) {
        List<TeacherScoreVO> teacherScoreVOs = new ArrayList<>();
        List<Topic> topics = topicService.listTopicBySeminarId(new BigInteger(seminarId));
        Iterator<Topic> topicIterator = topics.iterator();
        while (topicIterator.hasNext()) {
            Topic topic = topicIterator.next();
            List<SeminarGroup> seminarGroups = seminarGroupService.listGroupByTopicId(topic.getId());
            Iterator<SeminarGroup> seminarGroupIterator = seminarGroups.iterator();
            Integer i = 1;
            while (seminarGroupIterator.hasNext()) {
                SeminarGroup seminarGroup = seminarGroupIterator.next();
                TeacherScoreVO teacherScoreVO = new TeacherScoreVO();
                teacherScoreVO.setGroupId(seminarGroup.getId());
                teacherScoreVO.setTopicName(topic.getName());
                teacherScoreVO.setGroupName(topic.getSerial() + i.toString());
                teacherScoreVO.setLeader(seminarGroup.getLeader().getName());
                teacherScoreVO.setPresentationGrade(seminarGroup.getPresentationGrade());
                teacherScoreVO.setReportGrade(seminarGroup.getReportGrade());
                teacherScoreVO.setReportStatus(seminarGroup.getReport() == null ? "未提交" : "已提交");
                teacherScoreVO.setReport(seminarGroup.getReport());
                teacherScoreVO.setFinalGrade(seminarGroup.getFinalGrade());
                teacherScoreVOs.add(teacherScoreVO);
                ++i;
            }
        }
        return teacherScoreVOs;
    }

    @GetMapping("/{seminarId}/group/my")
    @ResponseStatus(HttpStatus.OK)
    public SeminarGroupDetail getMyGroup(@PathVariable("seminarId") String seminarId,@RequestAttribute("userId") String userId)
            throws GroupNotFoundException,UserNotFoundException {
        SeminarGroupDetail seminarGroupDetail=new SeminarGroupDetail();

        SeminarGroup seminarGroup = seminarGroupService.getSeminarGroupById(new BigInteger(seminarId), new BigInteger(userId));
        seminarGroupDetail.setId(seminarGroup.getId());
        seminarGroupDetail.setName(seminarGroup.getId().toString());
        BigInteger leaderId = seminarGroupService.getSeminarGroupLeaderByGroupId(seminarGroup.getId());
        User leader = userService.getUserByUserId(leaderId);

        UserIdNameVO leaderVO = new UserIdNameVO(leader);
        seminarGroupDetail.setLeader(leaderVO);

        List<UserIdNameVO> members = new ArrayList<>();
        List<User> seminarGroupMembers;
        seminarGroupMembers = seminarGroupService.listSeminarGroupMemberByGroupId(seminarGroup.getId());
        for (User user : seminarGroupMembers
                ) {
            UserIdNameVO userIdNameVO = new UserIdNameVO(user);
            if (!user.getId().equals(leader.getId())) {
                members.add(userIdNameVO);
            }
        }
        seminarGroupDetail.setMembers(members);

        return seminarGroupDetail;
    }

    @GetMapping("/{seminarId}/class/{classId}/attendance")
    @ResponseStatus(HttpStatus.OK)
    public AttendanceStatus getAttendanceStatus(@PathVariable("seminarId") String seminarId,
                                                @PathVariable("classId") String classId)
            throws ClassesNotFoundException, SeminarNotFoundException, UserNotFoundException {
        AttendanceStatus attendanceStatus = new AttendanceStatus();

        List<Attendance> attendances = userService.listAttendanceById(new BigInteger(classId), new BigInteger(seminarId));
        attendanceStatus.setNumPresent(attendances.size());

        List<User> students = userService.listUserByClassId(new BigInteger(classId), "", "");
        attendanceStatus.setNumStudent(students.size());

        Location location = classService.getCallStatusById(new BigInteger(classId), new BigInteger(seminarId));
        if (location.getStatus() == 0) {
            attendanceStatus.setStatus("签到结束");
            attendanceStatus.setGroup("已分组");
        } else {
            attendanceStatus.setStatus("正在签到");
            attendanceStatus.setGroup("未完成分组");
        }

        return attendanceStatus;
    }

    @GetMapping("/{seminarId}/class/{classId}/attendance/present")
    @ResponseStatus(HttpStatus.OK)
    public List<UserIdNameVO> getPresent(@PathVariable("seminarId") String seminarId,
                                         @PathVariable("classId") String classId)
            throws ClassesNotFoundException, SeminarNotFoundException {
        List<UserIdNameVO> userIdNameVOS = new ArrayList<>();
        List<User> presents;

        presents = userService.listPresentStudent(new BigInteger(seminarId), new BigInteger(classId));
        for (User present : presents
                ) {
            userIdNameVOS.add(new UserIdNameVO(present));
        }

        return userIdNameVOS;
    }

    @GetMapping("/{seminarId}/class/{classId}/attendance/late")
    @ResponseStatus(HttpStatus.OK)
    public List<UserIdNameVO> getLate(@PathVariable("seminarId") String seminarId,
                                      @PathVariable("classId") String classId)
            throws ClassesNotFoundException, SeminarNotFoundException {
        List<UserIdNameVO> lateStudents = new ArrayList<>();
        List<User> lates = userService.listLateStudent(new BigInteger(seminarId), new BigInteger(classId));
        for (User late : lates
                ) {
            lateStudents.add(new UserIdNameVO(late));
        }
        return lateStudents;
    }

    @GetMapping("/{seminarId}/class/{classId}/attendance/absent")
    @ResponseStatus(HttpStatus.OK)
    public List<UserIdNameVO> getAbsent(@PathVariable("seminarId") String seminarId,
                                        @PathVariable("classId") String classId)
            throws ClassesNotFoundException, SeminarNotFoundException {
        List<UserIdNameVO> userIdNameVOS = new ArrayList<>();
        List<User> absents = userService.listAbsenceStudent(new BigInteger(seminarId), new BigInteger(classId));
        for (User absent : absents
                ) {
            userIdNameVOS.add(new UserIdNameVO(absent));
        }
        return userIdNameVOS;
    }

    @PutMapping("/{seminarId}/class/{classId}/attendance/{studentId}")
    @ResponseStatus(HttpStatus.OK)
    public Status signIn(@PathVariable("seminarId") String seminarId,
                         @PathVariable("classId") String classId,
                         @PathVariable("studentId") String studentId,
                         @RequestBody SiteVO site)
            throws SeminarNotFoundException, ClassesNotFoundException, UserNotFoundException {
        Status status = new Status();

        Location location = classService.getCallStatusById(new BigInteger(classId), new BigInteger(seminarId));
        userService.insertAttendanceById(new BigInteger(classId), new BigInteger(seminarId), new BigInteger(studentId)
                , site.getLongitude(), site.getLatitude());
        if (location.getStatus() == 1) {
            status.setStatus("ontime");
        } else {
            status.setStatus("late");
        }

        return status;
    }
}
